home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / kernel / memory.c < prev    next >
C/C++ Source or Header  |  1990-07-23  |  6KB  |  171 lines

  1. /* This file contains the drivers for the following special files:
  2.  *     /dev/null    - null device (data sink)
  3.  *     /dev/mem        - absolute memory
  4.  *     /dev/kmem    - kernel virtual memory
  5.  *     /dev/ram        - RAM disk
  6.  *     /dev/port    - i/o ports ((CHIP == INTEL) only)
  7.  *
  8.  * The driver supports the following operations (using message format m2):
  9.  *
  10.  *    m_type      DEVICE    PROC_NR     COUNT    POSITION  ADRRESS
  11.  * ----------------------------------------------------------------
  12.  * |  DISK_READ | device  | proc nr |  bytes  |  offset | buf ptr |
  13.  * |------------+---------+---------+---------+---------+---------|
  14.  * | DISK_WRITE | device  | proc nr |  bytes  |  offset | buf ptr |
  15.  * |------------+---------+---------+---------+---------+---------|
  16.  * | DISK_IOCTL | device  |         |  blocks | ram org |         |
  17.  * ----------------------------------------------------------------
  18.  * |SCATTERED_IO| device  | proc nr | requests|         | iov ptr |
  19.  * ----------------------------------------------------------------
  20.  *  
  21.  *
  22.  * The file contains one entry point:
  23.  *
  24.  *   mem_task:    main entry when system is brought up
  25.  *
  26.  */
  27.  
  28. #include "kernel.h"
  29. #include <minix/callnr.h>
  30. #include <minix/com.h>
  31.  
  32. #ifdef PORT_DEV
  33. #define NR_RAMS            5    /* number of RAM-type devices */
  34. #else
  35. #define NR_RAMS            4
  36. #endif
  37. PRIVATE message mess;        /* message buffer */
  38. PRIVATE phys_bytes ram_origin[NR_RAMS];    /* origin of each RAM disk  */
  39. PRIVATE phys_bytes ram_limit[NR_RAMS];    /* limit of RAM disk per minor dev. */
  40.  
  41. FORWARD int do_mem();
  42. FORWARD int do_setup();
  43.  
  44. /*===========================================================================*
  45.  *                mem_task                     * 
  46.  *===========================================================================*/
  47. PUBLIC void mem_task()
  48. {
  49. /* Main program of the memory task. */
  50.  
  51.   int r, caller, proc_nr;
  52.  
  53.   /* Initialize this task. */
  54.   ram_origin[KMEM_DEV] = numap(SYSTASK, (vir_bytes) 0, (vir_bytes) 1);
  55.   ram_limit[KMEM_DEV] = ((phys_bytes) sizes[1] << CLICK_SHIFT) +
  56.                         ram_origin[KMEM_DEV];
  57. #if (CHIP == INTEL)
  58.   if (!protected_mode)
  59.     ram_limit[MEM_DEV] = 0x100000;    /* above 1M em_xfer word count fails */
  60.   else
  61.     ram_limit[MEM_DEV] = 0x1000000;    /* above 16M not mapped on 386 */
  62.   ram_limit[PORT_DEV] = 0x10000;
  63. #else
  64. #if (CHIP == M68000)
  65.   ram_limit[MEM_DEV] = MEM_BYTES;
  66. #else
  67. #error /* memory limit not set up */
  68. #endif
  69. #endif
  70.  
  71.   /* Here is the main loop of the memory task.  It waits for a message, carries
  72.    * it out, and sends a reply.
  73.    */
  74.   while (TRUE) {
  75.     /* First wait for a request to read or write. */
  76.     receive(ANY, &mess);
  77.     if (mess.m_source < 0)
  78.         panic("mem task got message from ", mess.m_source);
  79.     caller = mess.m_source;
  80.     proc_nr = mess.PROC_NR;
  81.  
  82.     /* Now carry out the work.  It depends on the opcode. */
  83.     switch(mess.m_type) {
  84.         case DISK_READ:    r = do_mem(&mess);    break;
  85.         case DISK_WRITE:    r = do_mem(&mess);    break;
  86.         case SCATTERED_IO:    r = do_vrdwt(&mess, do_mem); break;
  87.         case DISK_IOCTL:    r = do_setup(&mess);    break;
  88.         default:        r = EINVAL;        break;
  89.     }
  90.  
  91.     /* Finally, prepare and send the reply message. */
  92.     mess.m_type = TASK_REPLY;
  93.     mess.REP_PROC_NR = proc_nr;
  94.     mess.REP_STATUS = r;
  95.     send(caller, &mess);
  96.   }
  97. }
  98.  
  99.  
  100. /*===========================================================================*
  101.  *                do_mem                         * 
  102.  *===========================================================================*/
  103. PRIVATE int do_mem(m_ptr)
  104. register message *m_ptr;    /* pointer to read or write message */
  105. {
  106. /* Read or write /dev/null, /dev/mem, /dev/kmem, /dev/ram or /dev/port. */
  107.  
  108.   int device, count, endport, port, portval;
  109.   phys_bytes mem_phys, user_phys;
  110.  
  111.   /* Get minor device number and check for /dev/null. */
  112.   device = m_ptr->DEVICE;
  113.   if (device < 0 || device >= NR_RAMS) return(ENXIO);    /* bad minor device */
  114.   if (device==NULL_DEV) return(m_ptr->m_type == DISK_READ ? 0 : m_ptr->COUNT);
  115.  
  116.   /* Set up 'mem_phys' for /dev/mem, /dev/kmem, or /dev/ram. */
  117.   if (m_ptr->POSITION < 0) return(ENXIO);
  118.   mem_phys = ram_origin[device] + m_ptr->POSITION;
  119.   if (mem_phys >= ram_limit[device]) return(0);
  120.   count = m_ptr->COUNT;
  121.   if(mem_phys + count > ram_limit[device]) count = ram_limit[device] - mem_phys;
  122.  
  123.   /* Determine address where data is to go or to come from. */
  124.   user_phys = numap(m_ptr->PROC_NR, (vir_bytes) m_ptr->ADDRESS,
  125.             (vir_bytes) count);
  126.   if (user_phys == 0) return(E_BAD_ADDR);
  127.  
  128. #ifdef PORT_DEV
  129.   /* Do special case of /dev/port. */
  130.   if (device == PORT_DEV) {
  131.     port = mem_phys;
  132.     mem_phys = umap(proc_ptr, D, (vir_bytes) &portval, (vir_bytes) 1);
  133.     for (endport = port + count; port != endport; ++port) {
  134.         if (m_ptr->m_type == DISK_READ) {
  135.             portval = in_byte(port);
  136.             phys_copy(mem_phys, user_phys++, (phys_bytes) 1);
  137.         } else {
  138.             phys_copy(user_phys++, mem_phys, (phys_bytes) 1);
  139.             out_byte(port, portval);
  140.         }
  141.     }
  142.     return(count);
  143.   }
  144. #endif
  145.  
  146.   /* Copy the data. */
  147.   if (m_ptr->m_type == DISK_READ)
  148.     phys_copy(mem_phys, user_phys, (long) count);
  149.   else
  150.     phys_copy(user_phys, mem_phys, (long) count);
  151.   return(count);
  152. }
  153.  
  154.  
  155. /*===========================================================================*
  156.  *                do_setup                     * 
  157.  *===========================================================================*/
  158. PRIVATE int do_setup(m_ptr)
  159. message *m_ptr;            /* pointer to read or write message */
  160. {
  161. /* Set parameters for one of the disk RAMs. */
  162.  
  163.   int device;
  164.  
  165.   device = m_ptr->DEVICE;
  166.   if (device != RAM_DEV) return(ENXIO);    /* bad minor device */
  167.   ram_origin[device] = m_ptr->POSITION;
  168.   ram_limit[device] = m_ptr->POSITION + (long) m_ptr->COUNT * BLOCK_SIZE;
  169.   return(OK);
  170. }
  171.